#include "Estacionamiento.h"
Estacionamiento::Estacionamiento() {

}
Estacionamiento::Estacionamiento(long numeroEstacionamiento,
		int cantidadLugares, double precioPorHora) {
	this->numeroEstacionamiento = numeroEstacionamiento;
	this->cantidadLugares = cantidadLugares;
	std::string string = "./tmp/Lock" + to_string(this->numeroEstacionamiento);
	const char * archivoLock = string.c_str();
	this->lockEstacionamiento = new LockFile((char*) archivoLock);

	string = "./tmp/PlazasMem" + to_string(this->numeroEstacionamiento);
	const char* archivoPlazaEstacionamiento = string.c_str();
	//Para crear el archivo si no existe
	int fd = open(archivoPlazaEstacionamiento, O_CREAT | O_WRONLY, 0777);
	close(fd);
	this->plazasEstacionamiento.crear((char*) archivoPlazaEstacionamiento, 'A',
			cantidadLugares);
	for (int i = 0; i < cantidadLugares; i++) {
		PlazaEstacionamiento plaza(i);
		this->plazasEstacionamiento.escribir(cantidadLugares, plaza);
	}
	this->administrador = new Administrador(this->numeroEstacionamiento,
			precioPorHora);

}

int Estacionamiento::getCantidadLugares() {
	return this->cantidadLugares;
}

Administrador* Estacionamiento::getAdministrador() {
	return this->administrador;
}

void Estacionamiento::sacarAuto(Auto * autoSalido) {
	this->desocuparPlaza(autoSalido->getPos());
	this->administrador->sacarAuto(autoSalido);
}
void Estacionamiento::sacarAuto(int posicionOcupada, int tiempoOcupado) {
	this->desocuparPlaza(posicionOcupada);
	this->administrador->sacarAuto(tiempoOcupado);
}
void Estacionamiento::lockPlaza(int pos) {
	this->lockEstacionamiento->tomarLock(pos);
}

void Estacionamiento::unlock(int pos) {
	this->lockEstacionamiento->liberarLock(pos);
}

void Estacionamiento::desocuparPlaza(int pos) {
	this->lockPlaza(pos);
	PlazaEstacionamiento * plaza;
	plaza = this->plazasEstacionamiento.leer(pos);
	plaza->desocupar();
	this->plazasEstacionamiento.escribir(pos, *plaza);
	this->unlock(pos);
}

void Estacionamiento::ocuparPlaza(int pos) {
	this->lockPlaza(pos);
	PlazaEstacionamiento * plaza;
	plaza = this->plazasEstacionamiento.leer(pos);
	plaza->ocupar();
	this->plazasEstacionamiento.escribir(pos, *plaza);
	this->unlock(pos);
}

int Estacionamiento::getPosicionLibre() {
	if (this->cantidadLugares == this->administrador->consultarCantidadAutos())
		return -1;
	int pos;
	pos = Utils::calcularRandom(this->cantidadLugares);
	this->lockPlaza(pos);
	PlazaEstacionamiento * plaza = this->plazasEstacionamiento.leer(pos);
	if (plaza->isOcupado()) {
		this->unlock(pos);
		pos = this->getPosicionLibre();
	} else {
		plaza->ocupar();
		this->plazasEstacionamiento.escribir(pos, *plaza);
		this->unlock(pos);
	}
	return pos;
}

void Estacionamiento::estaciona(Auto * autoEntrando) {
	this->administrador->entraAuto();
}

void Estacionamiento::liberarMemoria() {
	this->plazasEstacionamiento.liberar();
	this->administrador->liberarMemoria();
	delete this->lockEstacionamiento;
	delete this->administrador;
}

Estacionamiento::~Estacionamiento() {

}

